<?php

include_once $_SERVER['DOCUMENT_ROOT']."/phorm/graphics/BitmapDimensions.php";

class Bitmap
{

	public $bitmapData;
	public $witdh;
	public $height;
	public $type;
	public $quality;
	
	public static function initWithFile($filenameWithPath)
	{
		$instance = new Bitmap();
		
		list($instance->width, $instance->height, $instance->type) = getimagesize($filenameWithPath);
		
		switch ($instance->type)
		{
			case IMAGETYPE_GIF:
				$instance->bitmapData = imagecreatefromgif($filenameWithPath);
				break;
				
			case IMAGETYPE_JPEG:
				$instance->bitmapData = imagecreatefromjpeg($filenameWithPath);
				break;
				
			case IMAGETYPE_PNG:
				$instance->bitmapData = imagecreatefrompng($filenameWithPath);
				break;
		}

		return $instance;
	}
	
	public function __construct($width=null, $height=null, $type=null, $quality=null, $bitmapData=null)
	{
		$this->width      = $width;
		$this->height     = $height;
		$this->type       = $type;
		$this->quality    = $quality;
		$this->bitmapData = $bitmapData;
	}
	
	public function getBounds()
	{
		//(left, upper, right, lower)
		return array(0, 0, $this->width, $this->height);
	}
	
	//                 0     1      2      3
	// array $bounds (left, upper, right, lower)
	public function crop($bounds)
	{
		$width  = $bounds[2] - $bounds[0];
		$height = $bounds[3] - $bounds[1];
		
		$cropped = imagecreatetruecolor($width, $height);
		imagecopyresampled ($cropped, $this->bitmapData, 0, 0, $bounds[0], $bounds[1], $bounds[2], $bounds[3], $bounds[2], $bounds[3]); 

		return new Bitmap($width, $height, $this->type, 80, $cropped);
	}

	public function resize(BitmapDimensions $dimensions)
	{	
		// constrain porportionally to width
		/*if (!$dimensions->height)
		{
			$dimensions->height = $this->calculatePorportion($dimensions->width, $this->width, $this->height); //ceil($a1 / $a * $b);
		}
		// constrain porportionally to height
		else if (! $dimensions->width)
		{
			$dimensions->width = $this->calculatePorportion($dimensions->height, $this->height, $this->width); //ceil($a1 / $a * $b);
		}*/

		//if ($dimensions->transformationHint)
		//{
			$bounds = $this->getBounds();
			switch ($dimensions->transformationHint)
			{
				case BitmapDimensions::kTransformCropFitHeight:
					$this->cropToHeight($bounds, $dimensions);
					$this->setValuesWithBitmap($this->crop($bounds));
					break;
				
				case BitmapDimensions::kTransformCropFitWidth:
					$this->cropToWidth($bounds, $dimensions);
					$this->setValuesWithBitmap($this->crop($bounds));
					break;
				
				case BitmapDimensions::kTransformCropFit:
					$this->cropToFit($bounds, $dimensions);
					$this->setValuesWithBitmap($this->crop($bounds));
					break;
				
				case BitmapDimensions::kTransformDynamicFit:
					$this->dynamicResize($bounds, $dimensions);
					break;
				
				case BitmapDimensions::kTransformStaticFit:
					break;
				
				case BitmapDimensions::kTransformProportionalWidth:
					$dimensions->width = $this->calculatePorportion($dimensions->height, $this->height, $this->width);
					break;
						
				case BitmapDimensions::kTransformProportionalHeight:
					$dimensions->height = $this->calculatePorportion($dimensions->width, $this->width, $this->height);
					break;
				
				default:
					break;
			}
		//}
		
		switch ($this->type)
		{
			case IMAGETYPE_GIF:
				return $this->resizeGIF($dimensions);
				break;

			case IMAGETYPE_JPEG:
				return $this->resizeJPG($dimensions);
				break;
			
			case IMAGETYPE_PNG:
				return $this->resizeJPG($dimensions);
				break;
		}
	}
	
	private function setValuesWithBitmap(Bitmap $a)
	{
		$this->width      = $a->width;
		$this->height     = $a->height;
		$this->bitmapData = $a->bitmapData;
		$this->type       = $a->type;
		$this->quality    = $a->quality;
	}
	
	private function dynamicResize(&$bounds, BitmapDimensions &$dimensions)
	{
		if($this->width >= $this->height){
			$dimensions->height = $this->calculatePorportion($dimensions->width, $this->width, $this->height);
		}
		else if ($this->height > $this->width){
			$dimensions->width = $this->calculatePorportion($dimensions->height, $this->height, $this->width);
		}
	}

	private function cropToHeight(&$bounds, BitmapDimensions &$dimensions)
	{
		$aspectRatio = $dimensions->width / $dimensions->height;
		$newHeight = $this->width / $aspectRatio;
		
		$left  = 0;
		$upper = ($this->height - $newHeight) / 2;
		$right = $this->width;
		$lower = $this->height - $upper;
		
		$bounds = array(floor($left), floor($upper), floor($right), floor($lower));
	}

	private function cropToWidth(&$bounds, BitmapDimensions &$dimensions)
	{
		$aspectRatio = $dimensions->width / $dimensions->height;
		$newWidth = $this->height * $aspectRatio;
		
		$left  = ($this->width - $newWidth) / 2;
		$upper = 0;
		$right = $this->width - $left;
		$lower = $this->height;
		
		$bounds = array(floor($left), floor($upper), floor($right), floor($lower));
	}

	private function cropToFit(&$bounds, BitmapDimensions &$dimensions)
	{	
		$aspectRatio = $dimensions->width / $dimensions->height;
		$newHeight = $this->width / $aspectRatio;
		
		if($newHeight > $this->height)
			$this->cropToWidth($bounds, $dimensions);			
		else
			$this->cropToHeight($bounds, $dimensions);			
	}

	private function resizeGIF(BitmapDimensions $dimensions)
	{
		$resize = imagecreatetruecolor($dimensions->width, $dimensions->height); 
		imagecopyresampled ($resize, $this->bitmapData, 0, 0, 0, 0, $dimensions->width, $dimensions->height, $this->width, $this->height); 
		
		//imagecopyresized($resize, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height); 
		
		return new Bitmap($dimensions->width, $dimensions->height, $this->type, $dimensions->quality, $resize);
		
	}
	
	private function resizeJPG(BitmapDimensions $dimensions)
	{
		$resize = imagecreatetruecolor($dimensions->width, $dimensions->height); 
		imagecopyresampled ($resize, $this->bitmapData, 0, 0, 0, 0, $dimensions->width, $dimensions->height, $this->width, $this->height); 
		
		//imagecopyresized($resize, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height); 
		
		return new Bitmap($dimensions->width, $dimensions->height, $this->type, $dimensions->quality, $resize);
	}
	
	private function calculatePorportion($a1, $a, $b)
	{	
		return ceil($a1 / $a * $b);
	}
	
	public function draw()
	{
		switch ($this->type)
		{
			case IMAGETYPE_GIF:
				return imagegif($this->bitmapData);
				break;

			case IMAGETYPE_JPEG:
				return imagejpeg($this->bitmapData);
				break;
			
			case IMAGETYPE_PNG:
				return imagepng($this->bitmapData);
				break;
				
		}
	}
	
	public function save($filenameWithPath)
	{
		switch ($this->type)
		{
			case IMAGETYPE_GIF:
				imagegif($this->bitmapData, $filenameWithPath);
				break;
			
			case IMAGETYPE_JPEG:
				imagejpeg($this->bitmapData, $filenameWithPath, $this->quality);
				break;
			
			case IMAGETYPE_PNG:
				imagepng($this->bitmapData, $filenameWithPath);
				break;
		}
	}
}
?>
